﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using log4net;

namespace Cos.Core.Model.Configuration
{
    public sealed class InternalCameleonConfig
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(InternalCameleonConfig));

        public static readonly String ConfigurationKey = "configuration";

        // FIXME Remove this and move it to the media service
        public static readonly String MediaExtensionKey = "Media";

        // FIXME Remove this and move it to the media service
        public static readonly String MediaFreeExtensionKey = "MediaFree";

        // FIXME Remove this and move it to the correct location
        public static readonly String CameleonCmsUrlKey = "CAMELEON_CMS_URL";

        // FIXME Remove this and move it to the correct location
        public static readonly String CameleonCmsFormMediaPathKey = "CAMELEON_CMS_FORM_MEDIA_PATH";

        // FIXME Remove this and move it to the correct location
        public static readonly String CameleonMediaUrlKey = "CAMELEON_MEDIA_URL";

        // FIXME Remove this and move it to the correct location
        public static readonly String CameleonCmsMediaPathKey = "CAMELEON_CMS_MEDIA_PATH";

        // FIXME Remove this and move it to the correct location
        public static readonly String CameleonMediaFreeUrlKey = "CAMELEON_MEDIA_FREE_URL";

        // FIXME Remove this and move it to the media service
        public static readonly String ImageStoreLocationKey = "IMAGE_STORE_LOCATION";

        // FIXME Remove this and move it to the correct location
        public static readonly String SmtpServerKey = "SMTP_SERVER";

        // FIXME Remove this and move it to the correct location
        public static readonly String HttpServerKey = "HTTP_SERVER";

        // FIXME Remove this and move it to the correct location
        public static readonly String HttpsServerKey = "HTTPS_SERVER";

        // FIXME Remove this and move it to the correct location
        public static readonly String PreviewHttpServerKey = "PREVIEW_HTTP_SERVER";

        // FIXME Remove this and move it to the correct location
        public static readonly String PreviewHttpsServerKey = "PREVIEW_HTTPS_SERVER";

        /**
         * How often (in seconds) the menu cache should query the DAO layer to know if anything changed.
         */
        public static readonly String MenuCacheRefreshTimeKey = "cameleon.menu_cache.refresh_time";

        public static readonly String IndexRefreshTimeKey = "cameleon.index.refresh_time";

        public static readonly String UrlMenuGeneratorClassKey = "cameleon.url.generator_class";

        private static readonly IDictionary<String, Object> Configs = new Dictionary<String, Object>();

        private static bool _isDevMode = false;

        private InternalCameleonConfig()
        {
            
        }

        static InternalCameleonConfig()
        {
            Instance = new InternalCameleonConfig();
        }

        /**
         * @return the unique instance of this class
         */
        public static InternalCameleonConfig Instance { get; private set; }

        /**
         * Get a config.
         * 
         * @param key a key of the config
         * @param defaultValue default value if the key doesn't exist
         * @return return value
         */
        public static String GetString(String key, String defaultValue)
        {
            if (!Configs.ContainsKey(key))
            {
                return defaultValue;
            }

            return (String)Configs[key];
        }

        /**
         * Get a config.
         * 
         * @param key a key of the config
         * @param defaultValue default value
         * @return return value
         */
        public static int GetInteger(String key, int defaultValue)
        {
            if (!Configs.ContainsKey(key))
            {
                return defaultValue;
            }

            var value = Configs[key];

            if (value is int)
            {
                return (int)value;
            }
            else if (value is String)
            {
                return int.Parse((String)value);
            }
            else
            {
                return defaultValue;
            }

        }

        /**
         * Get a config.
         * 
         * @param key a key of the config
         * @param defaultValue default value
         * @return return value
         */
        public static Boolean GetBoolean(String key, Boolean defaultValue)
        {
            if (!Configs.ContainsKey(key))
            {
                return defaultValue;
            }

            var value = Configs[key];

            if (value is Boolean)
            {
                return (Boolean)value;
            }
            else if (value is String)
            {
                return Boolean.Parse((String)value);
            }
            else
            {
                return defaultValue;
            }
        }

        /**
         * Set a config
         * 
         * @param key the key of the config
         * @param value the value of the config
         */
        public static void AddConfig(String key, Object value)
        {
            Configs.Add(key, value);
        }

        ///**
        // * @return the isDevMode
        // */
        //public static bool IsDevMode()
        //{
        //    return isDevMode;
        //}

        /**
         * @param isDevMode the isDevMode to set
         */
        public static bool DevMode
        {
            get { return _isDevMode; }
            set { _isDevMode = value; }
        }

        /**
         * Set the cameleon media URL
         * 
         * @param cameleonCmsUrlParam the cameleon based URL
         */
        public void SetCameleonCmsUrl(String cameleonCmsUrlParam)
        {
            String cameleonCmsUrl = cameleonCmsUrlParam;
            if (!cameleonCmsUrl.EndsWith("/"))
            {
                cameleonCmsUrl += "/";
            }

            String cameleonMediaUrl = cameleonCmsUrl + MediaExtensionKey + "/";
            String cameleonMediaFreeUrl = cameleonCmsUrl + MediaFreeExtensionKey + "/";

            Configs.Add(CameleonMediaUrlKey, cameleonMediaUrl);
            Configs.Add(CameleonMediaFreeUrlKey, cameleonMediaFreeUrl);
        }

        /**
         * Set the cameleon form media path
         * 
         * @param cameleonCmsFormMediaPath the cameleon form media path
         */
        public void SetCameleonCmsFormMediaPath(string cameleonCmsFormMediaPath)
        {

            if (!cameleonCmsFormMediaPath.EndsWith(Path.PathSeparator.ToString()))
            {
                Configs.Add(CameleonCmsFormMediaPathKey, cameleonCmsFormMediaPath + Path.PathSeparator.ToString());
            }
            else
            {
                InternalCameleonConfig.AddConfig(CameleonCmsFormMediaPathKey, cameleonCmsFormMediaPath);
            }
        }

        /**
         * Set the cameleon media path
         * 
         * @param cameleonCmsMediaPath the cameleon media path
         */
        public void SetCameleonCmsMediaPath(String cameleonCmsMediaPath)
        {
            if (!cameleonCmsMediaPath.EndsWith(Path.PathSeparator.ToString()))
            {
                Configs.Add(CameleonCmsMediaPathKey, cameleonCmsMediaPath + Path.PathSeparator.ToString());
            }
            else
            {
                Configs.Add(CameleonCmsMediaPathKey, cameleonCmsMediaPath);
            }
        }

        /**
         * Set the image store location
         * 
         * @param imageStoreLocation set the image store location
         */
        public void SetImageStoreLocation(String imageStoreLocation)
        {
            Configs.Add(ImageStoreLocationKey, imageStoreLocation);
        }

        /**
         * @param smtpServer Set the smtp server
         */
        public void SetSmtpServer(String smtpServer)
        {
            Configs.Add(SmtpServerKey, smtpServer);
        }

        /**
         * Initialize the cache
         * 
         * @param servletContext the servlet context
         * @param configuration the properties configuration file
         */
        public void Init()
        {
            
            if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[ConfigurationKey]) &&
                "development".Equals(ConfigurationManager.AppSettings[ConfigurationKey]))
            {
                InternalCameleonConfig.DevMode = true;
            }

            try
            {
                SetCameleonCmsUrl(ConfigurationManager.AppSettings[CameleonCmsUrlKey]);
            }
            catch 
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error("No CAMELEON_CMS_URL parameter has been put in the web.xml.");
                }
            }

            try
            {
                SetCameleonCmsFormMediaPath(ConfigurationManager.AppSettings[CameleonCmsFormMediaPathKey]);
            }
            catch 
            {
                if (Logger.IsWarnEnabled)
                {
                    Logger.Warn("No REFRESH_TIME_ENABLED parameter has been put in the web.xml");
                }
            }

            try
            {
                SetCameleonCmsMediaPath(ConfigurationManager.AppSettings[CameleonCmsMediaPathKey]);
            }
            catch
            {
                if (Logger.IsWarnEnabled)
                {
                    Logger.Warn("No REFRESH_TIME_ENABLED parameter has been put in the web.xml");
                }
            }

            try
            {
                SetImageStoreLocation(ConfigurationManager.AppSettings[ImageStoreLocationKey]);
            }
            catch 
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error("No IMAGE_STORE_LOCATION parameter has been put in the web.xml.");
                }
            }

            try
            {
                SetSmtpServer(ConfigurationManager.AppSettings[SmtpServerKey]);
            }
            catch 
            {
                if (Logger.IsWarnEnabled)
                {
                    Logger.Warn("No REFRESH_TIME_ENABLED parameter has been put in the web.xml");
                }
            }

            // add all appsettings config
            ConfigurationManager.AppSettings.AllKeys
                .Where(k => !Configs.ContainsKey(k))
                .ToList()
                .ForEach(k => Configs.Add(k, ConfigurationManager.AppSettings[k]));
            /*
            //@SuppressWarnings("unchecked")
            Enumeration<String> initParamEnum = servletContext.getInitParameterNames();
            while (initParamEnum.hasMoreElements()) {
                String key = initParamEnum.nextElement();

                if (!InternalCameleonConfig.configs.containsKey(key)) {
                    InternalCameleonConfig.addConfig(key, servletContext.getInitParameter(key));
                }
            }

            if (configuration != null) {
                //@SuppressWarnings("unchecked")
                Iterator<String> configurationKeys = configuration.getKeys();
                while (configurationKeys.hasNext()) {
                    String key = configurationKeys.next();

                    if (!InternalCameleonConfig.configs.containsKey(key)) {
                        InternalCameleonConfig.addConfig(key, configuration.getString(key));
                    }
                }*/
        }
    }

}
